package sketch.specs;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.ExpressionStatement;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.Statement;
import org.eclipse.jdt.internal.core.dom.NaiveASTFlattener;

import sketch.ast.ASTUtils;
import sketch.util.Checker;

public class SimpleNameExhaustiveReplacementVisitor extends NaiveASTFlattener {
    public final SimpleName name;
    public final List<Expression> expressions;
	
	public SimpleNameExhaustiveReplacementVisitor(Map<SimpleName, List<Expression>> map) {
		Checker.checkNull(map, "The map input could not be null!");
		//System.out.println("replacement map: " + map);
		Checker.checkTrue(map.size() == 1, "Currently only support map size = 1");
		this.name = ((SimpleName[])map.keySet().toArray(new SimpleName[0]))[0];
		this.expressions = map.get(name);
	}
	
	@Override
	public boolean visit(ExpressionStatement exprStatement) {
		//System.out.println(exprStatement);
		Checker.checkTrue(exprStatement.getParent() instanceof Block, "assume the parent is block.");
		
		Block parentBlock = (Block)exprStatement.getParent();
		int index = parentBlock.statements().indexOf(exprStatement);
		Checker.checkTrue(index != -1, "error in block: " + parentBlock);
		
		Block newBlock = exprStatement.getAST().newBlock();
		parentBlock.statements().remove(index);
		
		Map<SimpleName, Expression> nameExprMap = new LinkedHashMap<SimpleName, Expression>();
		for(Expression expr : expressions) {
			nameExprMap.clear();
			nameExprMap.put(name, expr);
			SimpleNameReplaceVisitor visitor = new SimpleNameReplaceVisitor(nameExprMap);
			ExpressionStatement replicate_expr = ASTUtils.deepClone(exprStatement);
			replicate_expr.accept(visitor);
			newBlock.statements().add(replicate_expr);
			//parentBlock.statements().add(index, replicate_expr);
		}
		
		//
		parentBlock.statements().add(index, newBlock);
		
		return false; //super.visit(name);
	}
}
